package il.ac.technion.cs236700.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;

/**
 * A logger with break points.
 */
public class Log {
	private static final Map<Integer, Runnable> BREAKS = new HashMap<Integer, Runnable>();
	private static Logger log = new Logger(System.out);
	private static boolean enabled = true;

	public static void setFile(File f) throws FileNotFoundException {
		log = new Logger(f);
	}

	public static boolean enabled() {
		return enabled;
	}

	public static void enable() {
		enabled = true;
	}

	public static void disable() {
		enabled = false;
	}

	public static void log() {
		log("");
	}

	public static <T> T log(String s, T t) {
		logStr(s);
		log(t);
		return t;
	}

	public static <T> T log(T t) {
		logStr(String.valueOf(t));
		return t;
	}

	public static void flush() {
		log.flush();
	}

	private static void logStr(String s) {
		if (!enabled)
			return;
		log.println(s);
		Runnable cmd = BREAKS.get(new Integer(log.line()));
		if (cmd != null)
			cmd.run();
	}

	/**
	 * Instruct the Log to print the stack trace at certain output positions
	 * 
	 * @param lines
	 *            An array of integers indicating line numbers in the log's
	 *            output
	 */
	public static void dumpStackTraceAt(int... lines) {
		breakAt(new Runnable() {
			public void run() {
				printStackTrace();
			}
		}, lines);
	}

	/**
	 * Register a command object to be invoked at certain output positions
	 * 
	 * @param r
	 *            The command object
	 * @param lines
	 *            An array of integers indicating line numbers in the log's
	 *            output
	 */
	public static void breakAt(Runnable r, int... lines) {
		for (int line : lines)
			BREAKS.put(new Integer(line), r);
	}

	public static void printStackTrace() {
		flush();
		new Exception().printStackTrace(log.wr);
	}
}
